angular.module("ui.ssnau.draggable", [])
.directive("uiDraggable", function() {
      var isDragging = false;
      var curtain = $("<div class='waitable-container unselectable' onselectstart='e.preventDefault();return false;'  style='position:absolute;cursor:all-scroll;z-index:9999;top:0px;left:0px;bottom:0px;right:0px;'></div>");
      var pos = {};
      var mousemoveHandlers = [];
      var ndDoc = $(document);

      ndDoc.on("mouseup", clear);

      function clear() {
          isDragging = false;
          curtain.hide();
          mousemoveHandlers.forEach(function(f){
              ndDoc.off("mousemove", f);
          });
          mousemoveHandlers = [];
      }
      return function(scope, elem, attrs) {
          var config = scope.$eval(attrs.uiDraggableConfig),
              target = elem;

          if (config && config.target) {
              target = $(elem.parents(config.target)[0]);
          }

          elem.css("cursor", "all-scroll");

          elem.on("mousedown", function(e){
              //自已开始，往上找直到elem[0]（不包括elem[0]）,看看是否有绑定ng-click的
              //如果有，则取消mousedown的处理
              var ndTarget = $(e.target);
              var hasClickEvent = ndTarget.closest("[ng-click]", elem[0]).length;

              //再判断一下是否有`no-draggable`的东西，这是一个用于标记的属性
              if (hasClickEvent || ndTarget.closest("[no-draggable]", elem[0]).length) {
                  return;
              }

              isDragging = true;
              curtain.appendTo(target);
              curtain.show();

              pos = {
                  x: e.pageX || e.originalEvent.pageX,
                  y: e.pageY || e.originalEvent.pageY,
                  left: parseInt(target.css("left")),
                  top: parseInt(target.css("top"))
              };

              ndDoc.on("mousemove", mousemoveHandler);
              mousemoveHandlers.push(mousemoveHandler);
          });

          elem.on("mouseup", clear);

          target.on("mousemove", mousemoveHandler);

          function mousemoveHandler(e) {
              if (!isDragging) return;
              var cur = {
                  x: e.pageX || e.originalEvent.pageX,
                  y: e.pageY || e.originalEvent.pageY
              };

              var offsetX = cur.x - pos.x,
                  offsetY = cur.y - pos.y;

              target.css("top", pos.top + offsetY + "px");
              target.css("left", pos.left + offsetX + "px");
          }

      }
    });